DPRINTK("dispatch_debug_block_io: unimplemented\n");
}
-static void dispatch_probe_block_io(struct task_struct *p, int index)
+static void dispatch_create_segment(struct task_struct *p, int index)
{
- blk_ring_t *blk_ring = p->blk_ring_base;
- xv_disk_t *xvd;
- int result;
-
- if (p->domain != 0)
- {
- printk (KERN_ALERT "dispatch_create_segment called by dom%d\n", p->domain);
- make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1);
- return;
- }
- extern void ide_probe_devices(xen_disk_info_t *xdi);
- extern void scsi_probe_devices(xen_disk_info_t *xdi);
++ blk_ring_t *blk_ring = p->blk_ring_base;
++ xv_disk_t *xvd;
++ int result;
++
++ if (p->domain != 0)
++ {
++ DPRINTK("dispatch_create_segment called by dom%d\n", p->domain);
++ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1);
++ return;
++ }
+
- xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
- result = xen_segment_create(xvd);
++ xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
++ result = xen_segment_create(xvd);
+
- make_response(p, blk_ring->ring[index].req.id,
- XEN_BLOCK_SEG_CREATE, result);
- return;
++ make_response(p, blk_ring->ring[index].req.id,
++ XEN_BLOCK_SEG_CREATE, result);
++ return;
+}
+
+static void dispatch_delete_segment(struct task_struct *p, int index)
+{
+ DPRINTK("dispatch_delete_segment: unimplemented\n");
+}
+
+static void dispatch_probe_blk(struct task_struct *p, int index)
+{
+ extern void ide_probe_devices(xen_disk_info_t *xdi, int *count,
+ drive_t xdrives[]);
++ extern void scsi_probe_devices(xen_disk_info_t *xdi, int *count,
++ drive_t xdrives[]);
++
blk_ring_t *blk_ring = p->blk_ring_base;
xen_disk_info_t *xdi;
xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
- /*
- ** SMH: by convention we first probe IDE, then SCSI; the latter
- ** apppends per-device info to the end of the xdi structure.
- */
- ide_probe_devices(xdi);
- scsi_probe_devices(xdi);
+
- /* scsi_probe_devices(xdi, &num_xdrives, xdrives); */ /* future */
+ ide_probe_devices(xdi, &num_xdrives, xdrives);
++ scsi_probe_devices(xdi, &num_xdrives, xdrives);
+
+ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_BLK, 0);
+}
+
+static void dispatch_probe_seg(struct task_struct *p, int index)
+{
+ extern void xen_segment_probe(xen_disk_info_t *xdi, int *count);
+ blk_ring_t *blk_ring = p->blk_ring_base;
+ xen_disk_info_t *xdi;
+
+ xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
+ xen_segment_probe(xdi, &num_xdrives);
- make_response(p, blk_ring->ring[index].req.id, 0);
+ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_SEG, 0);
}
static void dispatch_rw_block_io(struct task_struct *p, int index)
/* set just the important bits of the buffer header */
memset (bh, 0, sizeof (struct buffer_head));
- if (xen_device == XHDA_MAJOR) phys_device = MKDEV(IDE0_MAJOR, 0);
- else if (xen_device == XHDB_MAJOR) phys_device = MKDEV(IDE1_MAJOR, 0);
- else if (xen_device == XHDC_MAJOR) phys_device = MKDEV(IDE2_MAJOR, 0);
- else if (xen_device == XHDD_MAJOR) phys_device = MKDEV(IDE3_MAJOR, 0);
- else
- {
- printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
- xen_device);
- BUG();
- }
-
- block_number = blk_ring->ring[index].req.block_number;
- sector_number = blk_ring->ring[index].req.sector_number;
+
+ /* map from virtual xeno devices to physical ide & scsi devices */
+ xen_device = blk_ring->ring[index].req.device;
+ if (IS_XHD_MAJOR(xen_device))
+ {
- int s;
- if (s = xen_segment_map_request(&phys_device, &block_number,
- §or_number,
- p, operation, xen_device,
- blk_ring->ring[index].req.block_number,
- blk_ring->ring[index].req.sector_number))
- {
- printk ("dispatch_rw_block_io: xen_segment_map_request status: %d\n",
- s);
- goto bad_descriptor;
- }
++ if (xen_device == XHDA_MAJOR) phys_device = MKDEV(IDE0_MAJOR, 0);
++ else if (xen_device == XHDB_MAJOR) phys_device = MKDEV(IDE1_MAJOR, 0);
++ else if (xen_device == XHDC_MAJOR) phys_device = MKDEV(IDE2_MAJOR, 0);
++ else if (xen_device == XHDD_MAJOR) phys_device = MKDEV(IDE3_MAJOR, 0);
++ else
++ {
++ printk(KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
++ xen_device);
++ BUG();
++ }
++
++ block_number = blk_ring->ring[index].req.block_number;
++ sector_number = blk_ring->ring[index].req.sector_number;
+ }
+ else if (IS_VHD_MAJOR(xen_device))
+ {
- printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
- xen_device);
- BUG();
++ int s;
++ if (s = xen_segment_map_request(&phys_device, &block_number,
++ §or_number,
++ p, operation, xen_device,
++ blk_ring->ring[index].req.block_number,
++ blk_ring->ring[index].req.sector_number))
++ {
++ DPRINTK("dispatch_rw_block_io: xen_seg_map_request status: %d\n", s);
++ goto bad_descriptor;
++ }
+ }
+ else
+ {
++ printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
++ xen_device);
++ BUG();
+ }
- bh->b_blocknr = blk_ring->ring[index].req.block_number;
+ bh->b_blocknr = block_number;
bh->b_size = size;
- bh->b_dev = blk_ring->ring[index].req.device;
-
- bh->b_rsector = blk_ring->ring[index].req.sector_number;
+ bh->b_dev = phys_device;
+ bh->b_rsector = sector_number;
bh->b_data = phys_to_virt(buffer);
bh->b_count.counter = 1;
bh->b_end_io = end_block_io_op;
return;
bad_descriptor:
- printk (KERN_ALERT "dispatch rw blockio bad descriptor\n");
- make_response(p, blk_ring->ring[index].req.id, 1);
- return;
-}
++ DPRINTK("dispatch rw blockio bad descriptor\n");
+ make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_READ, 1);
- return;
+}
static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs)
{
- struct task_struct *p;
- blk_ring_t *blk_ring ;
++ struct task_struct *p;
++ blk_ring_t *blk_ring ;
+
- printk("Dumping block queue stats: nr_pending = %d\n",
- atomic_read(&nr_pending));
+ printk("Dumping block queue stats: nr_pending = %d\n",
+ atomic_read(&nr_pending));
+
- p = current->next_task;
- do
- {
- printk (KERN_ALERT "Domain: %d\n", p->domain);
- blk_ring = p->blk_ring_base;
++ p = current->next_task;
++ do
++ {
++ printk (KERN_ALERT "Domain: %d\n", p->domain);
++ blk_ring = p->blk_ring_base;
+
- printk(" req_prod:%d, resp_prod:%d, req_cons:%d\n",
- blk_ring->req_prod, blk_ring->resp_prod, p->blk_req_cons);
++ printk(" req_prod:%d, resp_prod:%d, req_cons:%d\n",
++ blk_ring->req_prod, blk_ring->resp_prod, p->blk_req_cons);
+
- p = p->next_task;
- } while (p != current);
++ p = p->next_task;
++ } while (p != current);
}
/* Start-of-day initialisation for a new domain. */
#include <asm/hypervisor-ifs/block.h>
#include <asm/hypervisor-ifs/hypervisor-if.h>
#include <asm/io.h>
+#include <asm/atomic.h>
#include <asm/uaccess.h>
- #define MAJOR_NR XLBLK_MAJOR /* force defns in blk.h, must precede include */
- static int xlblk_major = XLBLK_MAJOR;
#include <linux/blk.h>
/* Copied from linux/ide.h */
typedef unsigned char byte;
- #define XLBLK_MAX 32 /* Maximum minor devices we support */
- #define XLBLK_MAJOR_NAME "xhd"
- #define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
- #define IDE_PARTN_MASK ((1<<IDE_PARTN_BITS)-1) /* from ide.h::PARTN_MASK */
- static int xlblk_blk_size[XLBLK_MAX];
- static int xlblk_blksize_size[XLBLK_MAX];
- static int xlblk_read_ahead;
- static int xlblk_hardsect_size[XLBLK_MAX];
- static int xlblk_max_sectors[XLBLK_MAX];
-
+ extern int xlide_init(int xidx, int idx);
+ extern int xlide_hwsect(int minor);
+ extern void xlide_cleanup(void);
+ extern int xlscsi_init(int xidx, int idx);
+ extern int xlscsi_hwsect(int minor);
+ extern void xlscsi_cleanup(void);
+
+ static int nide = 0; // number of IDE devices we have
+ static int nscsi = 0; // number of SCSI devices we have
+
+
+ #define XLBLK_MAX 32 /* XXX SMH: this the max of XLIDE_MAX and XLSCSI_MAX */
#define XLBLK_RESPONSE_IRQ _EVENT_BLK_RESP
+
#define DEBUG_IRQ _EVENT_DEBUG
#if 0
static blk_ring_t *blk_ring;
static unsigned int resp_cons; /* Response consumer for comms ring. */
-xen_disk_info_t xen_disk_info;
-
-int hypervisor_request(void * id,
- int operation,
- char * buffer,
- unsigned long block_number,
- unsigned short block_size,
- kdev_t device);
+
+static xen_disk_info_t xlblk_disk_info;
+atomic_t xlblk_control_count;
+void xlblk_ide_register_disk(int, unsigned long);
+void do_xlseg_requestX (request_queue_t *rq);
+int hypervisor_request(void * id,
+ int operation,
+ char * buffer,
+ unsigned long block_number,
+ unsigned short block_size,
+ kdev_t device,
+ struct gendisk *gd);
-
/* ------------------------------------------------------------------------
*/
DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
command, (long) argument, minor_dev);
+ gd = xldev_to_gendisk(inode->i_rdev, &type);
+ part = &gd->part[minor_dev];
+
switch (command)
{
- case BLKGETSIZE: /* get size */
- DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE,
- (long) xlblk_disk_info.disks[0].capacity);
- return put_user(xlblk_disk_info.disks[0].capacity,
- (unsigned long *) argument);
+ case BLKGETSIZE:
+ DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects);
+ return put_user(part->nr_sects, (unsigned long *) argument);
- case BLKRRPART:
+ case BLKRRPART: /* re-read partition table */
DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART);
break;
- case BLKBSZGET: /* get block size */
- DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET);
- break;
+ case BLKSSZGET:
+ switch(type) {
+ case 1:
+ DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
+ xlide_hwsect(minor_dev));
+ return xlide_hwsect(minor_dev);
+ break;
+ case 2:
+ DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
+ xlscsi_hwsect(minor_dev));
+ return xlscsi_hwsect(minor_dev);
+ break;
+
+ default:
+ printk("BLKSSZGET ioctl() on bogus type %d disk!\n", type);
+ return 0;
+
+ }
+
+ case BLKBSZSET: /* set block size */
+ DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET);
+ break;
+
+ case BLKRASET: /* set read-ahead */
+ DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET);
+ break;
+
+ case BLKRAGET: /* get read-ahead */
+ DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET);
+ break;
+
+ case BLKSSZGET: /* get sector size */
+ DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
+ xlblk_hardsect_size[minor_dev]);
+ return xlblk_hardsect_size[minor_dev];
+
case HDIO_GETGEO:
+ /* note: these values are complete garbage */
DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO);
if (!argument) return -EINVAL;
if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT;
case XEN_BLOCK_READ:
case XEN_BLOCK_WRITE:
- /* only accept requests for xhd and vhd devices */
- if (!IS_XHD_MAJOR(MAJOR(device)) && !IS_VHD_MAJOR(MAJOR(device)))
- panic("error: xl_block::hypervisor_request: "
- "unknown device [0x%x]\n", device);
- phys_device = MAJOR(device);
--
- /* Compute real buffer location on disk.
- * note: gd will be null when we read the partition table.
- */
+ phys_device = xldev_to_physdev(device);
-
++ if (!IS_XHD_MAJOR(MAJOR(device)))
++ phys_device = MAJOR(device);
+ /* Compute real buffer location on disk */
sector_number = block_number;
- if ( gd != NULL )
- {
- sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect;
- }
-
- /*
- if (IS_VHD_MAJOR(MAJOR(device)))
- {
- printk (KERN_ALERT "%lx + %lx = %lx (%x)\n",
- block_number,
- gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect,
- sector_number, device);
- }
- */
+ gd = xldev_to_gendisk(device, NULL);
+ sector_number += gd->part[MINOR(device)].start_sect;
break;
default:
resp_cons = i;
/* KAF: We can push work down at this point. We have the lock. */
- /* aho: okay, so this is a bit of a hack. we'll kick every queue... */
- do_xlblk_request(BLK_DEFAULT_QUEUE(XLBLK_MAJOR));
- do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
-
+ for (i = 0; i < xen_disk_info.count; i++) {
+ /*
+ ** XXX SMH: this is pretty broken ...
+ ** a) should really only kick devs w/ outstanding work
+ ** b) should cover /all/ devs, not just first IDE & SCSI
+ ** KAF will fix this I'm sure.
+ */
+ do_xlblk_request(BLK_DEFAULT_QUEUE(IDE0_MAJOR));
+ do_xlblk_request(BLK_DEFAULT_QUEUE(SCSI_DISK0_MAJOR));
++ do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
+ }
+
spin_unlock_irqrestore(&io_request_lock, flags);
}
BUG();
HYPERVISOR_block_io_op();
while ( blk_ring->resp_prod != 1 ) barrier();
- printk (KERN_ALERT "xhd block device probe:\n");
-
- for ( i = 0; i < xen_disk_info.count; i++ )
+ for ( i = 0; i < xlblk_disk_info.count; i++ )
{
+ /*
+ ** SMH: initialize all the disks we found; this is complicated a
+ ** bit by the fact that we have both IDE and SCSI disks underneath
+ */
printk (KERN_ALERT " %2d: type: %d, capacity: %ld\n",
- i, xen_disk_info.disks[i].type,
- xen_disk_info.disks[i].capacity);
+ i, xlblk_disk_info.disks[i].type,
+ xlblk_disk_info.disks[i].capacity);
+
+ switch(xen_disk_info.disks[i].type) {
+ case 1:
+ xlide_init(i, nide++);
+ break;
+ case 2:
+ xlscsi_init(i, nscsi++);
+ break;
+ default:
+ printk("Unknown Xen disk type %d\n", xen_disk_info.disks[i].type);
+ break;
+ }
-
}
-
- SET_MODULE_OWNER(&xenolinux_block_fops);
- result = register_blkdev(xlblk_major, "block", &xenolinux_block_fops);
- if (result < 0) {
- printk (KERN_ALERT "xenolinux block: can't get major %d\n",
- xlblk_major);
- return result;
- }
-
- /* initialize global arrays in drivers/block/ll_rw_block.c */
- for (i = 0; i < XLBLK_MAX; i++) {
- xlblk_blk_size[i] = xlblk_disk_info.disks[0].capacity;
- xlblk_blksize_size[i] = 512;
- xlblk_hardsect_size[i] = 512;
- xlblk_max_sectors[i] = 128;
- }
- xlblk_read_ahead = 8;
-
- blk_size[xlblk_major] = xlblk_blk_size;
- blksize_size[xlblk_major] = xlblk_blksize_size;
- hardsect_size[xlblk_major] = xlblk_hardsect_size;
- read_ahead[xlblk_major] = xlblk_read_ahead;
- max_sectors[xlblk_major] = xlblk_max_sectors;
-
- blk_init_queue(BLK_DEFAULT_QUEUE(xlblk_major), do_xlblk_request);
-
- /*
- * Turn off barking 'headactive' mode. We dequeue buffer heads as
- * soon as we pass them down to Xen.
- */
- blk_queue_headactive(BLK_DEFAULT_QUEUE(xlblk_major), 0);
- xlblk_ide_register_disk(0, xlblk_disk_info.disks[0].capacity);
-
- printk(KERN_ALERT
- "XenoLinux Virtual Block Device Driver installed [device: %d]\n",
- xlblk_major);
return 0;
fail:
return error;
}
- void xlblk_ide_register_disk(int idx, unsigned long capacity)
- {
- int units;
- int minors;
- struct gendisk *gd;
-
- /* plagarized from ide-probe.c::init_gendisk */
-
- units = 2; /* from ide.h::MAX_DRIVES */
-
- minors = units * (1<<IDE_PARTN_BITS);
- gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
- gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
- gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
- memset(gd->part, 0, minors * sizeof(struct hd_struct));
-
- gd->major = xlblk_major;
- gd->major_name = XLBLK_MAJOR_NAME;
- gd->minor_shift = IDE_PARTN_BITS;
- gd->max_p = 1<<IDE_PARTN_BITS;
- gd->nr_real = units;
- gd->real_devices = NULL;
- gd->next = NULL;
- gd->fops = &xenolinux_block_fops;
- gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
- gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
-
- if (gd->de_arr)
- memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
-
- if (gd->flags)
- memset (gd->flags, 0, sizeof *gd->flags * units);
-
- add_gendisk(gd);
-
- xlblk_disk_info.disks[idx].gendisk = gd;
-
- register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS,
- &xenolinux_block_fops, capacity);
-
- {
- int loop = 0;
- printk (KERN_ALERT "Partition Table: (capacity: %lx)\n", capacity);
- for (loop = 0; loop < minors; loop++)
- {
- if (gd->part[loop].start_sect && gd->part[loop].nr_sects)
- {
- printk (KERN_ALERT
- " %2d: 0x%6lx %8ld 0x%6lx %7ld\n", loop,
- gd->part[loop].start_sect, gd->part[loop].start_sect,
- gd->part[loop].nr_sects, gd->part[loop].nr_sects);
- }
- }
- }
-
- return;
- }
-
-
--
static void __exit xlblk_cleanup(void)
{
- /* CHANGE FOR MULTIQUEUE */
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlblk_major));
-
- /* clean up global arrays */
- read_ahead[xlblk_major] = 0;
-
- if (blk_size[xlblk_major])
- kfree(blk_size[xlblk_major]);
- blk_size[xlblk_major] = NULL;
+ int i;
- if (blksize_size[xlblk_major])
- kfree(blksize_size[xlblk_major]);
- blksize_size[xlblk_major] = NULL;
+ for ( i = 0; i < xen_disk_info.count; i++ )
+ {
+ switch(xen_disk_info.disks[i].type) {
+ case 1:
+ xlide_cleanup();
+ break;
+ case 2:
+ xlscsi_cleanup();
+ break;
+ default:
+ printk("Unknown Xen disk type %d\n", xen_disk_info.disks[i].type);
+ break;
+ }
- if (hardsect_size[xlblk_major])
- kfree(hardsect_size[xlblk_major]);
- hardsect_size[xlblk_major] = NULL;
-
- /* XXX: free each gendisk */
- if (unregister_blkdev(xlblk_major, "block"))
- printk(KERN_ALERT
- "XenoLinux Virtual Block Device Driver uninstalled w/ errs\n");
- else
- printk(KERN_ALERT
- "XenoLinux Virtual Block Device Driver uninstalled\n");
+ }
return;
}